package com.stu.collection;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Java集合基础演示
 * 涵盖：
 * - Collection和Collections的区别
 * - List、Set、Map的区别
 * - 常见集合类的特性
 * - 线程安全的集合
 * - Comparable和Comparator接口
 * 
 * @author 学习者
 * @version 1.0
 */
public class CollectionBasics {
    
    public static void main(String[] args) {
        System.out.println("=== Java集合基础演示 ===");
        
        // 1. Collection和Collections的区别
        demonstrateCollectionVsCollections();
        
        // 2. List、Set、Map的区别
        demonstrateCollectionTypes();
        
        // 3. 线程安全的集合
        demonstrateThreadSafeCollections();
        
        // 4. Comparable和Comparator演示
        demonstrateComparableAndComparator();
        
        // 5. 集合的泛型使用
        demonstrateGenerics();
    }
    
    /**
     * 演示Collection和Collections的区别
     */
    private static void demonstrateCollectionVsCollections() {
        System.out.println("\n=== Collection和Collections的区别 ===");
        
        System.out.println("Collection：");
        System.out.println("- 是一个接口，集合框架的根接口");
        System.out.println("- 定义了集合的基本操作方法");
        System.out.println("- 被List、Set、Queue等接口继承");
        
        System.out.println("\nCollections：");
        System.out.println("- 是一个工具类，提供静态方法操作集合");
        System.out.println("- 提供排序、搜索、同步等功能");
        
        // Collections工具类演示
        List<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(1);
        list.add(4);
        list.add(2);
        
        System.out.println("\nCollections工具类使用示例：");
        System.out.println("原始列表：" + list);
        
        // 排序
        Collections.sort(list);
        System.out.println("排序后：" + list);
        
        // 反转
        Collections.reverse(list);
        System.out.println("反转后：" + list);
        
        // 打乱
        Collections.shuffle(list);
        System.out.println("打乱后：" + list);
        
        // 二分查找（需要先排序）
        Collections.sort(list);
        int index = Collections.binarySearch(list, 3);
        System.out.println("查找元素3的索引：" + index);
        
        // 获取最大值和最小值
        System.out.println("最大值：" + Collections.max(list));
        System.out.println("最小值：" + Collections.min(list));
        
        // 创建不可修改的集合
        List<Integer> unmodifiableList = Collections.unmodifiableList(list);
        System.out.println("不可修改的列表：" + unmodifiableList);
        try {
            unmodifiableList.add(5);
        } catch (UnsupportedOperationException e) {
            System.out.println("尝试修改不可修改列表时抛出异常：" + e.getClass().getSimpleName());
        }
    }
    
    /**
     * 演示List、Set、Map的区别
     */
    private static void demonstrateCollectionTypes() {
        System.out.println("\n=== List、Set、Map的区别演示 ===");
        
        // List演示
        System.out.println("\nList特性演示：");
        List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Apple"); // 允许重复
        list.add(null);    // 允许null
        
        System.out.println("List内容：" + list);
        System.out.println("List特点：有序、允许重复、允许null、支持索引访问");
        System.out.println("通过索引访问：list.get(0) = " + list.get(0));
        System.out.println("查找元素索引：list.indexOf(\"Apple\") = " + list.indexOf("Apple"));
        
        // Set演示
        System.out.println("\nSet特性演示：");
        Set<String> set = new HashSet<>();
        set.add("Apple");
        set.add("Banana");
        set.add("Apple"); // 重复元素不会被添加
        set.add(null);    // 允许一个null
        
        System.out.println("Set内容：" + set);
        System.out.println("Set特点：无序（HashSet）、不允许重复、最多一个null");
        System.out.println("Set大小：" + set.size());
        
        // LinkedHashSet演示（保持插入顺序）
        Set<String> linkedSet = new LinkedHashSet<>();
        linkedSet.add("First");
        linkedSet.add("Second");
        linkedSet.add("Third");
        System.out.println("LinkedHashSet（保持插入顺序）：" + linkedSet);
        
        // TreeSet演示（自然排序）
        Set<String> treeSet = new TreeSet<>();
        treeSet.add("Zebra");
        treeSet.add("Apple");
        treeSet.add("Banana");
        System.out.println("TreeSet（自然排序）：" + treeSet);
        
        // Map演示
        System.out.println("\nMap特性演示：");
        Map<String, Integer> map = new HashMap<>();
        map.put("Apple", 10);
        map.put("Banana", 20);
        map.put("Orange", 15);
        map.put(null, 5);     // 允许null键
        map.put("Grape", null); // 允许null值
        
        System.out.println("Map内容：" + map);
        System.out.println("Map特点：键值对存储、键唯一、值可重复");
        System.out.println("通过键获取值：map.get(\"Apple\") = " + map.get("Apple"));
        System.out.println("所有键：" + map.keySet());
        System.out.println("所有值：" + map.values());
        System.out.println("所有键值对：" + map.entrySet());
        
        // Map的遍历方式
        System.out.println("\nMap的遍历方式：");
        System.out.println("1. 遍历键值对：");
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println("  " + entry.getKey() + " = " + entry.getValue());
        }
        
        System.out.println("2. 遍历键：");
        for (String key : map.keySet()) {
            System.out.println("  " + key + " = " + map.get(key));
        }
        
        System.out.println("3. 遍历值：");
        for (Integer value : map.values()) {
            System.out.println("  值：" + value);
        }
        
        // 为什么Map不继承Collection
        System.out.println("\n为什么Map不继承Collection？");
        System.out.println("1. Collection存储单一元素，Map存储键值对");
        System.out.println("2. Collection的方法如add(E)不适用于Map");
        System.out.println("3. Map有自己特有的操作如put(K,V)、get(K)等");
        System.out.println("4. 设计上Map是独立的接口体系");
    }
    
    /**
     * 演示线程安全的集合
     */
    private static void demonstrateThreadSafeCollections() {
        System.out.println("\n=== 线程安全的集合演示 ===");
        
        System.out.println("常用的线程安全集合：");
        
        // 1. Vector（线程安全的List）
        Vector<String> vector = new Vector<>();
        vector.add("Vector元素1");
        vector.add("Vector元素2");
        System.out.println("1. Vector（线程安全的List）：" + vector);
        
        // 2. Hashtable（线程安全的Map）
        Hashtable<String, String> hashtable = new Hashtable<>();
        hashtable.put("key1", "value1");
        hashtable.put("key2", "value2");
        System.out.println("2. Hashtable（线程安全的Map）：" + hashtable);
        
        // 3. ConcurrentHashMap（高性能线程安全Map）
        ConcurrentHashMap<String, String> concurrentMap = new ConcurrentHashMap<>();
        concurrentMap.put("concurrent1", "value1");
        concurrentMap.put("concurrent2", "value2");
        System.out.println("3. ConcurrentHashMap：" + concurrentMap);
        
        // 4. CopyOnWriteArrayList（读多写少场景）
        CopyOnWriteArrayList<String> cowList = new CopyOnWriteArrayList<>();
        cowList.add("COW元素1");
        cowList.add("COW元素2");
        System.out.println("4. CopyOnWriteArrayList：" + cowList);
        
        // 5. Collections.synchronizedXxx（包装现有集合）
        List<String> syncList = Collections.synchronizedList(new ArrayList<>());
        syncList.add("同步列表元素");
        System.out.println("5. Collections.synchronizedList：" + syncList);
        
        // 线程安全集合的特点对比
        System.out.println("\n线程安全集合特点对比：");
        System.out.println("Vector vs ArrayList：");
        System.out.println("  - Vector：线程安全，性能较低，方法加synchronized");
        System.out.println("  - ArrayList：非线程安全，性能较高");
        
        System.out.println("\nHashtable vs HashMap：");
        System.out.println("  - Hashtable：线程安全，不允许null键值，继承Dictionary");
        System.out.println("  - HashMap：非线程安全，允许null键值，继承AbstractMap");
        
        System.out.println("\nConcurrentHashMap vs Hashtable：");
        System.out.println("  - ConcurrentHashMap：分段锁，性能更好，JDK8后使用CAS+synchronized");
        System.out.println("  - Hashtable：全表锁，性能较差");
        
        System.out.println("\nCopyOnWriteArrayList特点：");
        System.out.println("  - 读操作无锁，写操作复制整个数组");
        System.out.println("  - 适合读多写少的场景");
        System.out.println("  - 内存占用较大，写操作性能较差");
    }
    
    /**
     * 演示Comparable和Comparator接口
     */
    private static void demonstrateComparableAndComparator() {
        System.out.println("\n=== Comparable和Comparator接口演示 ===");
        
        // Comparable接口演示
        System.out.println("\nComparable接口演示：");
        List<Student> students = new ArrayList<>();
        students.add(new Student("张三", 85));
        students.add(new Student("李四", 92));
        students.add(new Student("王五", 78));
        
        System.out.println("排序前：" + students);
        Collections.sort(students); // 使用Comparable的自然排序
        System.out.println("按分数排序后：" + students);
        
        // Comparator接口演示
        System.out.println("\nComparator接口演示：");
        
        // 按姓名排序
        Collections.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                return s1.getName().compareTo(s2.getName());
            }
        });
        System.out.println("按姓名排序：" + students);
        
        // 使用Lambda表达式
        Collections.sort(students, (s1, s2) -> Integer.compare(s2.getScore(), s1.getScore()));
        System.out.println("按分数降序排序（Lambda）：" + students);
        
        // 使用方法引用
        Collections.sort(students, Comparator.comparing(Student::getName));
        System.out.println("按姓名排序（方法引用）：" + students);
        
        // 多级排序
        Collections.sort(students, 
            Comparator.comparing(Student::getScore)
                     .thenComparing(Student::getName));
        System.out.println("先按分数后按姓名排序：" + students);
        
        System.out.println("\nComparable vs Comparator：");
        System.out.println("Comparable：");
        System.out.println("  - 内部比较器，类自身实现");
        System.out.println("  - 只能有一种排序方式");
        System.out.println("  - 实现compareTo方法");
        
        System.out.println("Comparator：");
        System.out.println("  - 外部比较器，独立的比较逻辑");
        System.out.println("  - 可以有多种排序方式");
        System.out.println("  - 实现compare方法");
        System.out.println("  - 支持Lambda表达式和方法引用");
    }
    
    /**
     * 演示集合的泛型使用
     */
    private static void demonstrateGenerics() {
        System.out.println("\n=== 集合泛型使用演示 ===");
        
        System.out.println("使用泛型的优点：");
        System.out.println("1. 类型安全：编译时检查类型");
        System.out.println("2. 消除强制类型转换");
        System.out.println("3. 提高代码可读性");
        
        // 不使用泛型（不推荐）
        System.out.println("\n不使用泛型的问题：");
        List rawList = new ArrayList();
        rawList.add("字符串");
        rawList.add(123);
        rawList.add(new Date());
        
        for (Object obj : rawList) {
            // 需要强制类型转换，可能出现ClassCastException
            if (obj instanceof String) {
                String str = (String) obj;
                System.out.println("字符串：" + str);
            } else if (obj instanceof Integer) {
                Integer num = (Integer) obj;
                System.out.println("整数：" + num);
            }
        }
        
        // 使用泛型（推荐）
        System.out.println("\n使用泛型的好处：");
        List<String> stringList = new ArrayList<>();
        stringList.add("Hello");
        stringList.add("World");
        // stringList.add(123); // 编译错误，类型不匹配
        
        for (String str : stringList) {
            // 不需要强制类型转换
            System.out.println("字符串长度：" + str.length());
        }
        
        // 泛型通配符
        System.out.println("\n泛型通配符演示：");
        
        // ? extends T（上界通配符）
        List<? extends Number> numberList = new ArrayList<Integer>();
        // numberList.add(1); // 编译错误，不能添加元素
        
        // ? super T（下界通配符）
        List<? super Integer> superList = new ArrayList<Number>();
        superList.add(1); // 可以添加Integer及其子类
        
        System.out.println("通配符规则：");
        System.out.println("? extends T：只能读取，不能写入（除了null）");
        System.out.println("? super T：可以写入T及其子类，读取时需要转换为Object");
        System.out.println("?：等同于? extends Object");
    }
}

/**
 * 学生类，实现Comparable接口
 */
class Student implements Comparable<Student> {
    private String name;
    private int score;
    
    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }
    
    public String getName() {
        return name;
    }
    
    public int getScore() {
        return score;
    }
    
    /**
     * 实现Comparable接口，按分数升序排序
     */
    @Override
    public int compareTo(Student other) {
        return Integer.compare(this.score, other.score);
    }
    
    @Override
    public String toString() {
        return name + "(" + score + ")";
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Student student = (Student) obj;
        return score == student.score && Objects.equals(name, student.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, score);
    }
}